package com.dayuanit.dy17.mix.single;

public class Fish {

    //volatile关键字：能够解决线程可见的问题；还能解决指令重排序的问题。
    //volatile不能解决线程安全的问题，也就是不能解决并发的问题
    private volatile static Fish fish;

    private Fish() {

    }

    //在加锁之前先判断fish对象，这个是减少了锁的粒度，能够提升性能；
    //但是，在并发情况下，会有bug。有些线程拿到的Fish对象可能是未初始化好的。
    public static Fish getFish() {
        //双重校验
        if (fish == null) {
            synchronized (Fish.class) {
                if (fish == null) {
                    //由于创建对象需要三步走：
                    //1.分配内存空间
                    //2.对象初始化
                    //3.赋值
                    //其中，第1步一定在2和3先执行；第2和3步可以并行执行。这样就会导致2和3执行的顺序可能会颠倒。
                    //万一，第3步早于第2步执行，那么就会出现有些线程拿到的对象是一个半成品，还没有初始化好的对象。
                    //产生这种原因是虚拟机在底层会对指令做重排序，也就是为了提升指令执行的速度，充分利用CPU资源。
                    //指令重排序是虚拟机为了提升性能。(CPU指令流水线)
                    //禁止指令重排序的方法：为属性加上volatile关键字
                    fish = new Fish();
                }
            }
        }
        return fish;
    }


}
